package utils

import (
	"context"
	"log/slog"

	"golang.org/x/sync/errgroup"
)

// LimitConcurrent 执行给定的任务函数，并限制并发数
func LimitConcurrent(tasks []func() error, limit int) error {
	ctx, cancel := context.WithCancel(context.Background())
	defer cancel()
	g, ctx := errgroup.WithContext(ctx)

	// 并发限制
	g.SetLimit(limit)
	// semaphore := make(chan struct{}, limit)

	for _, task := range tasks {
		task := task // 防止闭包问题
		// semaphore <- struct{}{} // 申请一个名额
		g.Go(func() error {
			// defer func() { <-semaphore }()
			select {
			case <-ctx.Done():
				// 发生错误时取消上下文
				slog.Error("任务执行失败", "error", ctx.Err())
				return ctx.Err()
			default:
				if err := task(); err != nil {
					slog.Error("任务执行失败", "error", err)
					cancel()
					return err
				}
			}
			return nil
		})
	}

	// 等待所有协程完成或发生错误
	if err := g.Wait(); err != nil {
		return err
	}

	return nil
}
